<template>
    <div class="roles">
        <div>
            <auth-group-list :select="true" :show-share="false" :sub-height="135" @data-list="getAuthGroupList" @change="changeAuthGroup"></auth-group-list>
        </div>
        <div>
            <div class="page-action-btn">
                <el-button v-if="UIAuth._api_admin_roles_post" type="primary" @click="showAdd">添加</el-button>
                <el-button v-if="UIAuth._api_admin_roles_post" type="success" @click="copyRole">复制角色</el-button>
                <el-button v-if="UIAuth._api_admin_roles_put" type="warning" @click="showEdit">修改</el-button>
                <p-confirm-btn v-if="UIAuth._api_admin_roles_delete" @confirm="del"></p-confirm-btn>
            </div>
            <div v-if="UIAuth._api_admin_roles_paginate_get">
                <p-table ref="pTable" v-loading="loading" :data="dataList" :sub-height="175" :show-paginate="true" v-model="paginate" @row-click="rowClick" @row-dblclick="showEdit"
                    @row-clear="rowClear" @selection-change="selectionChange" @paginate="getList">
                    <el-table-column prop="role_name" label="角色名称" width="200"></el-table-column>
                    <el-table-column prop="role_type" label="角色类型" width="95">
                        <template v-slot="{ row }">
                            <user-type :type="row.role_type"></user-type>
                        </template>
                    </el-table-column>
                    <el-table-column prop="desc" label="备注" min-width="360"></el-table-column>
                </p-table>
            </div>
            <p-el-dialog v-model="showDialog" :title="`${isEdit ? '修改' : '添加'}权限角色`" width="65%" @opened="editOpened" :height="bodySize.height - 130" @close="dialogClose"
                @confirm="isEdit ? edit() : add()" :ok-text="isEdit ? '修改' : '添加'">
                <el-form :model="params" status-icon :rules="paramsRules" ref="elForm" label-width="120px">
                    <el-form-item label="角色名称" prop="role_name">
                        <el-input v-model="params.role_name" placeholder="请输角色名称"></el-input>
                    </el-form-item>
                    <el-form-item label="角色类型" prop="role_type">
                        <el-select v-model="params.role_type" placeholder="请选择角色类型">
                            <el-option v-for="(item, key) in accountTypeArray" :key="key" :label="item.label" :value="item.val"></el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="所属权限组" prop="auth_group_id">
                        <el-select v-model="params.auth_group_id" placeholder="请选择" @change="selectAuthGroupChange">
                            <el-option label="请选择" value=""></el-option>
                            <el-option v-for="item in authGroupList" :key="item.id" :label="item.title" :value="item.id"></el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="备注">
                        <el-input type="textarea" :row="5" v-model="params.desc" placeholder="请输入备注"></el-input>
                    </el-form-item>
                </el-form>
                <div class="roles-tree">
                    <div :style="rolesBranchOpen?'width:60%':'width:100%'">
                        <div>选择【菜单】权限（可以通过所属部门获得）</div>
                        <div>
                            <el-tree :data="authTreeList" show-checkbox node-key="id" :default-expand-all="true" @check-change="authChickChange" ref="authTree"
                                :props="{ children: 'children', label: 'title' }">
                                <template v-slot="{ node, data }">
                                    <div class="roles-tree-auth">
                                        <div class="roles-tree-auth-title">{{ data.title }}</div>
                                        <div class="roles-tree-auth-api" v-show="data.api_list && data.api_list.length > 0">
                                            <el-checkbox-group v-model="data.checkedApiCode">
                                                <div v-for="item in apiIdGetAuthApi(data.api_list)" :key="item.id">
                                                    <el-checkbox :label="item.auth_code" :disabled="!node.checked">
                                                        {{ item.title }}
                                                    </el-checkbox>
                                                </div>
                                            </el-checkbox-group>
                                        </div>
                                    </div>
                                </template>
                            </el-tree>
                        </div>
                    </div>
                    <div v-if="rolesBranchOpen">
                        <div>选择【部门机构】权限</div>
                        <div>
                            <el-tree :data="branchTreeList" show-checkbox :default-expand-all="true" node-key="id" ref="branchTree" :props="{ children: 'children', label: 'branch_name' }"></el-tree>
                        </div>
                    </div>
                </div>
            </p-el-dialog>
        </div>
    </div>
</template>

<script lang="ts">
import {defineComponent, onMounted, reactive, ref, toRefs} from "vue";
import {useStore} from "vuex";
import {IPaginate, defaultPaginate} from "@/lib/IApp";
import PTable from "@/components/PTable.vue";
import PElDialog from "@/components/PElDialog.vue";
import valid from "@/lib/valid";
import http from "@/lib/http/http";
import PConfirmBtn from "@/components/PConfirmBtn.vue";
import message from "@/lib/message";
import utils from "@/lib/utils";
import UserType from "@/components/user/UserType.vue";
import AuthGroupList from "@/components/auth/AuthGroupList.vue";
import TreeTool from "@/lib/TreeTool";
import AccountType, {AccountTypeArray} from "@/lib/user/AccountType";
import storage from "@/lib/storage/storage";
import config from "@/config";

const ParamsRules: any = {
    role_name: [{required: true, message: "请输入角色名称", trigger: "blur"}],
    auth_group_id: [
        {
            required: true,
            message: "请选择角色所属权限组",
            trigger: ["blur", "change"],
        },
    ],
    role_type: [
        {
            required: true,
            message: "请选择角色类型",
            trigger: ["blur", "change"],
        },
    ],
};

/**
 * state 数据类型
 */
interface IState {
    rolesBranchOpen: boolean; // 是否开启角色 【角色】可以选择部门机构
    loading: boolean;
    paginate: IPaginate; // 分页数据
    dataList: any[]; // 获取到的数据列表
    showDialog: boolean; // 是否显示 添加编辑窗口
    isEdit: boolean; // 是否修改
    isCopy: boolean; // 是否复制
    params: any; // http 请求参数
    paramsRules: any; // 参数校验
    tableRow: any; // 单选选择的行内容
    tableRows: any[]; // 多选选择的行内容
    branchList: any[]; // 部门机构列表
    branchTreeList: any[]; // 部门机构列表
    apiList: any[]; // api接口列表
    authList: any[]; // 菜单权限列表
    authTreeList: any[]; // 菜单权限列表
    authGroupList: any[]; // 权限组列表
    selectAuthGroup: any; // 选择的菜单权限组
    search: any; // 搜索条件
    user: any; // 用户信息
    userBranchID: string[]; // 用户拥有的部门机构ID
    account_type: number; // 登陆用户权限类型
    accountTypeArray: any[]; // 账号类型数组
    accountType: number; // 当前登陆用户的账号类型
}

export default defineComponent({
    name: "Roles",
    components: {PTable, PElDialog, PConfirmBtn, AuthGroupList, UserType},
    setup() {
        const store = useStore();
        const {UIAuth, bodySize} = toRefs(store.state);
        const treeTool: TreeTool = new TreeTool();
        const pTable: any = ref<any>();
        const authTree: any = ref<any>();
        const branchTree: any = ref<any>();
        const elForm: any = ref<any>();
        const state = reactive<IState>({
            rolesBranchOpen: config.rolesBranchOpen, // 是否开启角色 【角色】可以选择部门机构
            loading: false,
            paginate: defaultPaginate, // 分页数据
            dataList: [], // 获取到的数据列表
            showDialog: false, // 是否显示 添加编辑窗口
            isEdit: false, // 是否修改
            isCopy: false, // 是否复制
            params: {}, // http 请求参数
            paramsRules: ParamsRules, // 参数校验
            tableRow: null, // 单选选择的行内容
            tableRows: [], // 多选选择的行内容
            branchList: [], // 部门机构列表
            branchTreeList: [], // 部门机构列表
            apiList: [], // api接口列表
            authList: [], // 菜单权限列表
            authTreeList: [], // 菜单权限列表
            authGroupList: [], // 权限组列表
            selectAuthGroup: null, // 选择的菜单权限组
            search: {auth_group_id: ""}, // 搜索条件
            user: {}, // 用户信息
            userBranchID: [], // 用户拥有的部门机构ID
            account_type: 0, // 登陆用户权限类型
            accountTypeArray: [], // 账号类型数组
            accountType: 0, // 当前登陆用户的账号类型
        });

        function getLoginUserInfo() {
            store.dispatch("getLoginUserInfo");
        }

        // 获取API接口数据接口
        function getApiList() {
            http.Get(`/api`, {auth_group_id: state.selectAuthGroup.id})
                .then((data) => {
                    state.apiList = data;
                })
                .catch((err) => "");
        }

        // 获取菜单权限组
        function getAuthGroupList(data: any) {
            state.authGroupList = data;
        }

        // 选择 菜单权限组
        function changeAuthGroup(val: any) {
            state.dataList = [];
            state.selectAuthGroup = val;
            state.tableRows = [];
            state.tableRow = null;
            pTable.value.clearSelect();
            if (val != null) {
                state.search.auth_group_id = val.id;
                getApiList();
                getList();
                getAuthList(val.id);
            }
        }

        // select组件选择 菜单权限组
        function selectAuthGroupChange(id: string) {
            message.loadingShow("获取菜单权限中");
            authTree.value.setCheckedKeys([]);
            getAuthList(id);
        }

        // 获取部门机构列表
        function getBranchList() {
            http.Get(`/branch`)
                .then((data) => {
                    if (data != null) {
                        if (state.account_type !== AccountType.SYSTEM_ADMIN) {
                            data.forEach((item: any) => {
                                item.disabled = true;
                                for (const bid of state.userBranchID) {
                                    if (bid === item.id) {
                                        item.disabled = false;
                                        break;
                                    }
                                }
                            });
                        }
                        state.branchList = utils.CopyNewObject(data);
                        state.branchTreeList = treeTool.listToTree(data, "");
                    }
                })
                .catch((err) => "");
        }

        // 菜单权限列表
        function getAuthList(authGroupId: string = "") {
            state.authList = [];
            state.authTreeList = [];
            http.Get(`/auth/${authGroupId}`)
                .then((data) => {
                    if (data != null) {
                        data.forEach((item: any) => {
                            item.disabled = 0;
                            item.checkedApiCode = [];
                        });
                        state.authList = utils.CopyNewObject(data);
                        state.authTreeList = treeTool.listToTree(data, "");
                    }
                })
                .catch((err) => "");
        }

        // 获取菜单权限对应的API接口
        function apiIdGetAuthApi(codes: string[] = []): any[] {
            if (utils.empty(codes)) {
                return [];
            }
            const resArr: any[] = [];
            state.apiList.forEach((item: any) => {
                codes.forEach((code: string) => {
                    if (item.auth_code === code) {
                        resArr.push(item);
                    }
                });
            });
            return resArr;
        }

        // 权限菜单 节点选中状态发生变化时的回调
        function authChickChange(row: any, check: boolean) {
            row.checkedApiCode = [];
            if (utils.empty(row.api_list)) {
                return;
            }
            if ((state.isEdit || state.isCopy) && state.params.api_code.length > 0) {
                row.api_list.forEach((code: string) => {
                    const index = state.params.api_code.findIndex((c: string) => c == code);
                    if (index >= 0) {
                        row.checkedApiCode.push(code);
                    }
                });
            }
        }

        // 单击选中
        function rowClick(val: any) {
            state.tableRow = val.row;
        }

        // 取消选中
        function rowClear() {
            state.tableRow = null;
        }

        // 关闭添加修改窗口
        function dialogClose() {
            state.showDialog = false;
            state.isEdit = false;
            state.isCopy = false;
            state.branchTreeList = treeTool.listToTree(
                utils.CopyNewObject(state.branchList),
                ""
            );
            state.authTreeList = treeTool.listToTree(
                utils.CopyNewObject(state.authList),
                ""
            );
            authTree.value.setCheckedKeys([]);
            if (state.rolesBranchOpen) {
                branchTree.value.setCheckedKeys([]);
            }
            state.params = {
                auth_group_id: "",
                branch_id: [],
                auth_id: [],
                default_api_code: [],
                api_code: [],
            };
        }

        // 多选时触发
        function selectionChange(val: any[]): void {
            state.tableRows = val;
        }

        // 显示添加
        function showAdd() {
            state.params = {
                auth_group_id: "",
                branch_id: [],
                auth_id: [],
                default_api_code: [],
                api_code: [],
            };
            if (state.selectAuthGroup != null) {
                state.params.auth_group_id = state.selectAuthGroup.id;
            }
            state.isCopy = false;
            state.isEdit = false;
            state.showDialog = true;
        }

        // 复制角色
        function copyRole() {
            if (state.tableRow == null) {
                message.error("请选择要复制的角色");
                return;
            }
            state.params.role_name = state.tableRow.role_name;
            state.params.role_type = state.tableRow.role_type;
            state.params.auth_group_id = state.selectAuthGroup.id;
            state.params.branch_id = utils.CopyNewObject(
                state.tableRow.branch_id
            );
            state.params.auth_id = utils.CopyNewObject(state.tableRow.auth_id);
            state.params.default_api_code = utils.CopyNewObject(
                state.tableRow.default_api_code
            );
            state.params.api_code = utils.CopyNewObject(
                state.tableRow.api_code
            );
            state.params.desc = state.tableRow.desc;
            state.isCopy = true;
            state.isEdit = false;
            state.showDialog = true;
        }

        // 获取内容
        function getList() {
            state.loading = true;
            http.Get(
                `/roles/${state.paginate.page_size}/${state.paginate.page}`,
                state.search
            )
                .then((data) => {
                    state.dataList = [];
                    data.data.forEach((item: any) => {
                        if (state.accountType > item.role_type) {
                            state.dataList.push(item);
                        }
                    });
                    state.paginate = data.paginate;
                    state.loading = false;
                })
                .catch((err) => (state.loading = false));
        }

        //保存前设置选择的权限
        function saveSetInitAuth() {
            const checkAuthList = authTree.value.getCheckedNodes(false, true);
            let checkBranchList = [];
            if (state.rolesBranchOpen) {
                checkBranchList = branchTree.value.getCheckedNodes(false, false);
            }
            state.params.branch_id = [];
            state.params.auth_id = [];
            state.params.default_api_code = [];
            state.params.api_code = [];
            checkAuthList.forEach((item: any) => {
                state.params.auth_id.push(item.id);
                item.default_api_list.forEach((code: string) => {
                    const index = state.params.default_api_code.findIndex((c: string) => c == code);
                    if (index < 0) {
                        state.params.default_api_code.push(code);
                    }
                });
                item.checkedApiCode.forEach((code: string) => {
                    const index = state.params.api_code.findIndex((c: string) => c == code);
                    if (index < 0) {
                        state.params.api_code.push(code);
                    }
                });
            });
            checkBranchList.forEach((item: any) => {
                state.params.branch_id.push(item.id);
            });
        }

        // 添加
        function add() {
            elForm.value.validate((ok: boolean) => {
                if (ok) {
                    saveSetInitAuth();
                    http.Post("/roles", state.params)
                        .then((data) => {
                            if (utils.empty(state.dataList)) {
                                state.dataList = [data];
                            } else {
                                state.dataList.unshift(data);
                            }
                            dialogClose();
                        })
                        .catch((err) => "");
                } else {
                    return false;
                }
            });
        }

        // 显示修改
        function showEdit() {
            if (state.tableRow == null) {
                message.error("请选择要修改的角色");
                return;
            }
            state.isEdit = true;
            state.params.role_name = state.tableRow.role_name;
            state.params.role_type = state.tableRow.role_type;
            state.params.auth_group_id = state.tableRow.auth_group_id;
            state.params.branch_id = utils.CopyNewObject(
                state.tableRow.branch_id
            );
            state.params.auth_id = utils.CopyNewObject(state.tableRow.auth_id);
            state.params.default_api_code = utils.CopyNewObject(
                state.tableRow.default_api_code
            );
            state.params.api_code = utils.CopyNewObject(
                state.tableRow.api_code
            );
            state.params.desc = state.tableRow.desc;

            state.params.id = state.tableRow.id;
            state.params.aid = state.tableRow.aid;
            state.params.version = state.tableRow.version;
            state.showDialog = true;
        }

        // 对话框打开完成回调
        function editOpened() {
            if (state.isEdit || state.isCopy) {
                const authIds: string[] = [];
                const branchIds: string[] = [];
                state.params.auth_id.forEach((id: string) => {
                    const authTem = treeTool.get(state.authTreeList, id);
                    if (!utils.empty(authTem)) {
                        if (
                            utils.empty(authTem.children) ||
                            authTem.children.length === 0
                        ) {
                            authIds.push(id);
                        }
                    }
                });
                authTree.value.setCheckedKeys(authIds);
                if (state.rolesBranchOpen) {
                    state.params.branch_id.forEach((id: string) => {
                        const branchTem = treeTool.get(
                            state.branchTreeList,
                            id
                        );
                        if (!utils.empty(branchTem)) {
                            if (
                                utils.empty(branchTem.children) ||
                                branchTem.children.length === 0
                            ) {
                                branchIds.push(id);
                            }
                        }
                    });
                    branchTree.value.setCheckedKeys(branchIds);
                }
            }
        }

        // 修改
        function edit() {
            elForm.value.validate((ok: boolean) => {
                if (ok) {
                    saveSetInitAuth();
                    http.Put("/roles", state.params).then((data) => {
                            const index = state.dataList.findIndex((item) => item.id === state.tableRow.id);
                            if (index >= 0) {
                                state.dataList.splice(index, 1, data);
                            }
                            dialogClose();
                            getLoginUserInfo();
                        }).catch((err) => "");
                } else {
                    return false;
                }
            });
        }

        // 删除
        function del() {
            const ids: string[] = [];
            if (state.tableRows.length === 0) {
                if (state.tableRow == null) {
                    message.error("请选择要删除的角色");
                    return;
                } else {
                    ids.push(state.tableRow.id);
                }
            }
            state.tableRows.forEach((item) => {
                ids.push(item.id);
            });
            message.loadingShow("删除中");
            http.Delete("/roles", {ids})
                .then((data) => {
                    ids.forEach((id) => {
                        const index = state.dataList.findIndex(
                            (item) => item.id === id
                        );
                        if (index >= 0) {
                            state.dataList.splice(index, 1);
                        }
                    });
                    getLoginUserInfo();
                })
                .catch((err) => "");
        }

        onMounted(() => {
            state.user = storage.user.Get();
            state.accountType = state.user.account.account_type;
            state.userBranchID = state.user.branch_id;
            state.account_type = state.user.account.account_type;
            if (state.account_type === AccountType.SYSTEM_ADMIN) {
                state.accountTypeArray = AccountTypeArray;
            } else {
                AccountTypeArray.forEach((item: any) => {
                    if (item.val < state.account_type) {
                        state.accountTypeArray.push(item);
                    }
                });
            }
            getBranchList();
        });
        return {
            UIAuth,
            bodySize,
            ...toRefs(state),
            pTable,
            authTree,
            branchTree,
            elForm,
            getApiList,
            getAuthGroupList,
            changeAuthGroup,
            selectAuthGroupChange,
            getBranchList,
            getAuthList,
            apiIdGetAuthApi,
            authChickChange,
            rowClick,
            rowClear,
            dialogClose,
            selectionChange,
            showAdd,
            copyRole,
            getList,
            add,
            showEdit,
            editOpened,
            edit,
            del,
        };
    },
});
</script>


<style>
.roles-tree .el-tree-node__content {
    height: auto;
}

.roles-tree .el-tree-node__content > label.el-checkbox {
    margin-right: 4px;
}

.roles-tree-auth-api .el-checkbox__label {
    padding-left: 5px;
}
</style>
<style scoped lang="scss">
.roles {
    display: flex;
    justify-content: space-between;

    & > div {
        &:first-child {
            width: 200px;
        }

        &:last-child {
            width: calc(100% - 210px);
        }
    }

    &-tree {
        display: flex;
        justify-content: space-between;

        & > div {
            &:first-child {
                width: 60%;
            }

            &:last-child {
                width: calc(40% - 5px);
            }

            & > div {
                &:first-child {
                    color: $text-secondary-color;
                    background-color: $border-color2;
                    padding: 8px;
                }

                &:last-child {
                    border: 1px $border-color2 solid;
                }
            }
        }

        &-auth {
            width: calc(100% - 45px);
            margin: 1px 0;

            &-title {
                padding: 5px;
                background-color: $border-color2;
            }

            &-api {
                border: 1px $border-color2 solid;

                & > * {
                    margin-left: 5px;

                    &:first-child {
                        margin-top: 5px;
                    }

                    &:last-child {
                        margin-bottom: 5px;
                    }
                }
            }
        }
    }
}
</style>
